#ifndef __studies_architecture_interacting__access_controller__h__
#define __studies_architecture_interacting__access_controller__h__


/** @file */


/** @todo */

// ==> C++ Headers
#include <string>
#include <functional>
#include <iostream>

// ==> 3rds Headers

// ==> Our Headers
#include "recover_pwd.h"
#include <studies.architecture.returns/codes.h>

// ==> Namespaces
using namespace std;

// ==> Macro Constants

// ==> Macro Commands


/** ==> namespace of the organization */
namespace studies {
    /** ==> namespace for the project */
    namespace architecture {
        /** ==> displaying, interacting, translation, message, processor, object, storer */
        namespace interacting {

            // ==> Typedefs 

            // ==> Pre-Declarations

            // ==> Attributes 

            // ==> Functions

            // ==> Classes

            /** 
                @nosubgrouping 
            */
            template <typename t_supplier>
            class access_controller_t {

                // ==> access_controller_t - Friends

                /** Class allowed to access private members of @p
                    access_controller_t, in order to perform tests */
                friend class access_controller_t_tester;

            public:

                // ==> access_controller_t - Public Internal Types

                /** */
                typedef t_supplier supplier;

                /** */
                typedef typename supplier::access_controller_transmitter transmitter;

                /** */
                typedef typename supplier::access_controller_displayer displayer;


                // ==> access_controller_t - Public Constructors

                /** */
                access_controller_t()
                    : m_transmitter(),
                      m_displayer(),
                      m_login(){}

                /** Destructor */
                ~access_controller_t( ) {}

                // ==> access_controller_t - Public Accessors

                /** */
                const std::string & get_login() {
                    return m_login;
                }

                // ==> access_controller_t - Public Helpers

                // ==> access_controller_t - Public Processors

                /** */
                void start() {
                    m_displayer.show(*this);
                }

                /** */
                bool allow() const {
                    return (!m_login.empty());
                }

                /** */
                void on_login_pwd_set(const std::string & p_login,
                                      const std::string & p_pwd) {

                    // in another thread
                    handle_login_pwd_set(p_login, p_pwd);
                    
                }

                /** */
                void recover_pwd() {
                    recover_pwd_t<supplier> l_recover_pwd;
                    l_recover_pwd.start();
                }
                
                
                // ==> access_controller_t - Public Operators

                // ==> access_controller_t - Public Attributes

            private:

                // ==> access_controller_t - Private Internal Types

                // ==> access_controller_t - Private Constructors

                // ==> access_controller_t - Private Accessors

                // ==> access_controller_t - Private Helpers

                // ==> access_controller_t - Private Processors

                /** */
                void handle_login_pwd_set(const std::string & p_login,
                                          const std::string & p_pwd) {
                    returns::codes l_rc = m_transmitter.is_access_valid(p_login,
                                                                        p_pwd);
                    if (l_rc == returns::codes::OK) {
                            m_login = p_login;
                    }
                    else {
                        m_login.clear();
                        m_displayer.show_error(l_rc);
                    }
                }
                

                // ==> access_controller_t - Private Operators

                // ==> access_controller_t - Private Attributes

                /** */
                transmitter m_transmitter;

                /** */
                displayer m_displayer;

                /** */
                std::string m_login;
                
                
            };
        }
    }
}
// =============================================================================
// I M P L E M E N T A T I O N
// =============================================================================

using namespace studies::architecture::interacting;


#endif
